/** * <copyright> * * Copyright (c) 2009, 2010 Springsite BV (The Netherlands) and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Martin Taal - Initial API and implementation * IBM - getInstanceClass method * * </copyright> * * $Id: GenUtils.java,v 1.16 2011/08/25 12:35:07 mtaal Exp $ */ package org.eclipse.emf.texo.modelgenerator.annotator; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import javax.xml.datatype.XMLGregorianCalendar; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.EFactory; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.impl.EPackageImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.emf.ecore.xml.type.XMLTypeFactory; import org.eclipse.emf.ecore.xml.type.XMLTypePackage; import org.eclipse.emf.texo.generator.AnnotationManager; import org.eclipse.emf.texo.generator.GeneratorUtils; import org.eclipse.emf.texo.model.ModelFactory; import org.eclipse.emf.texo.modelgenerator.modelannotations.EEnumModelGenAnnotation; import org.eclipse.emf.texo.modelgenerator.modelannotations.EPackageModelGenAnnotation; import org.eclipse.emf.texo.modelgenerator.modelannotations.ModelcodegeneratorPackage; import org.eclipse.emf.texo.utils.Check; import org.eclipse.emf.texo.utils.ModelUtils; import org.eclipse.xsd.ecore.NameMangler; /** * Utility methods for code/ui generation. Contains methods for default value computation and type computation for * EDataTypes. * * @author <a href="mtaal@elver.org">Martin Taal</a> */ public class GenUtils { private static final HashSet<String> javaWords; static { javaWords = new HashSet<String>(50); javaWords.add("true"); //$NON-NLS-1$ javaWords.add("false"); //$NON-NLS-1$ javaWords.add("abstract"); //$NON-NLS-1$ javaWords.add("continue");//$NON-NLS-1$ javaWords.add("for");//$NON-NLS-1$ javaWords.add("new");//$NON-NLS-1$ javaWords.add("switch");//$NON-NLS-1$ javaWords.add("assert");//$NON-NLS-1$ javaWords.add("default");//$NON-NLS-1$ javaWords.add("goto");//$NON-NLS-1$ javaWords.add("package");//$NON-NLS-1$ javaWords.add("synchronized");//$NON-NLS-1$ javaWords.add("boolean");//$NON-NLS-1$ javaWords.add("do");//$NON-NLS-1$ javaWords.add("if");//$NON-NLS-1$ javaWords.add("private");//$NON-NLS-1$ javaWords.add("this");//$NON-NLS-1$ javaWords.add("break");//$NON-NLS-1$ javaWords.add("double");//$NON-NLS-1$ javaWords.add("implements");//$NON-NLS-1$ javaWords.add("protected");//$NON-NLS-1$ javaWords.add("throw");//$NON-NLS-1$ javaWords.add("byte");//$NON-NLS-1$ javaWords.add("else");//$NON-NLS-1$ javaWords.add("import");//$NON-NLS-1$ javaWords.add("public");//$NON-NLS-1$ javaWords.add("throws");//$NON-NLS-1$ javaWords.add("case");//$NON-NLS-1$ javaWords.add("enum");//$NON-NLS-1$ javaWords.add("instanceof");//$NON-NLS-1$ javaWords.add("return");//$NON-NLS-1$ javaWords.add("transient");//$NON-NLS-1$ javaWords.add("catch");//$NON-NLS-1$ javaWords.add("extends");//$NON-NLS-1$ javaWords.add("int");//$NON-NLS-1$ javaWords.add("short");//$NON-NLS-1$ javaWords.add("try");//$NON-NLS-1$ javaWords.add("char");//$NON-NLS-1$ javaWords.add("final");//$NON-NLS-1$ javaWords.add("interface");//$NON-NLS-1$ javaWords.add("static");//$NON-NLS-1$ javaWords.add("void");//$NON-NLS-1$ javaWords.add("class");//$NON-NLS-1$ javaWords.add("finally");//$NON-NLS-1$ javaWords.add("long");//$NON-NLS-1$ javaWords.add("strictfp");//$NON-NLS-1$ javaWords.add("volatile");//$NON-NLS-1$ javaWords.add("const");//$NON-NLS-1$ javaWords.add("float");//$NON-NLS-1$ javaWords.add("native");//$NON-NLS-1$ javaWords.add("super");//$NON-NLS-1$ javaWords.add("while");//$NON-NLS-1$ } public static String cast(String type) { if (type == null) { return type; } if (type.equals(Object.class.getName())) { return ""; //$NON-NLS-1$ } return "(" + type + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } public static String correctTypeDef(String type) { if (type == null) { return null; } if (type.equals(Class.class.getName())) { return Class.class.getName() + "<?>"; //$NON-NLS-1$ } return type; } /** * @return true if the epackage is not a generated EMF epackage. * * Note will return true for the {@link EcorePackage} and {@link XMLTypePackage}. As from these packages the * instance classes should be used. */ public static boolean useInstanceClassNames(EPackage ePackage) { if (ePackage.getNsURI().equals(EcorePackage.eNS_URI) || ePackage.getNsURI().equals(XMLTypePackage.eNS_URI)) { return true; } return ePackage.getClass() == EPackageImpl.class; } /** * Determines the instance class of an EAttribute, if the EAttribute is isMany then it will return the class of the * elements in the collection. * * @param eAttribute * the EAttribute for which the type is computed * @returns the type of a many attribute */ public static Class<?> getEDataTypeClass(final EDataType eDataType) { final Class<?> instanceClass = eDataType.getInstanceClass(); if (instanceClass != null && !Object.class.equals(instanceClass) && !List.class.equals(instanceClass)) { if (instanceClass.isArray()) { return eDataType.getInstanceClass().getComponentType(); } return instanceClass; } // the type is hidden somewhere deep get it // the edatatype is the java.util.list // it has an itemType which is the name of the element edatatype // which contains the instanceclass // takes also into account inheritance between datatypes // NOTE the otm.targetentity can consist of a comma delimited list // of target // entities this is required for listunion types but is not // supported, in that case the first one is returned final EDataType itemType = ExtendedMetaData.INSTANCE.getItemType(eDataType); if (itemType != null) { return itemType.getInstanceClass(); } final List<EDataType> memberTypes = ExtendedMetaData.INSTANCE.getMemberTypes(eDataType); if (memberTypes != null && memberTypes.size() > 0) { return memberTypes.get(0).getInstanceClass(); } return Object.class; } /** * @param eClassifier * the eClassifier for which the name of the object type is returned. * @return the name of the object type if the eClassifier represents a primitive type. */ public static String getPrimitiveObjectType(final EClassifier eClassifier) { final Class<?> instanceClass = eClassifier.getInstanceClass(); if (instanceClass == null) { return null; } if (!instanceClass.isPrimitive()) { if (instanceClass.isArray()) { return instanceClass.getComponentType().getName() + "[]"; //$NON-NLS-1$ } return instanceClass.getName(); } final Class<?> objectClass = getObjectClass(instanceClass); if (objectClass != null) { return objectClass.getName(); } return null; } /** * Return the object class of a primitive java class, int --> Integer, long --> Long etc. If there is no object class * (e.g. if the instanceClass is not a primitive java class) then null is returned. */ public static Class<?> getObjectClass(Class<?> instanceClass) { if (XMLGregorianCalendar.class.isAssignableFrom(instanceClass)) { return Date.class; } else if (instanceClass == java.lang.Boolean.TYPE) { return Boolean.class; } else if (instanceClass == java.lang.Byte.TYPE) { return Byte.class; } else if (instanceClass == java.lang.Character.TYPE) { return Character.class; } else if (instanceClass == java.lang.Double.TYPE) { return Double.class; } else if (instanceClass == java.lang.Float.TYPE) { return Float.class; } else if (instanceClass == java.lang.Integer.TYPE) { return Integer.class; } else if (instanceClass == java.lang.Long.TYPE) { return Long.class; } else if (instanceClass == java.lang.Short.TYPE) { return Short.class; } return null; } /** * Checks if the passed word is a java reserved word. * * @param word * the word to check * @return in case the word is a java reserved word then it appends a _ */ public static String getValidJavaMemberName(final String word) { if (javaWords.contains(word)) { return lowerCaseFirst(word) + GenConstants.SAFE_NAME_POSTFIX; } return lowerCaseFirst(word); } private static String lowerCaseFirst(String value) { if (GeneratorUtils.isEmptyOrNull(value)) { return value; } if (value.length() == 1) { return value.toLowerCase(); } return value.substring(0, 1).toLowerCase() + value.substring(1); } /** * Translates an EPackage nsURI into a java package name, for example http://www.elver.org/test/codegen is translated * to org.elver.test.codegen. If the last entry in the path is equal to the package name then that is stripped off as * this is added later during code generation. Uses the EMF method to translate a namespace into a java package name. * * @param ePackage * the EPackage for which the java package name is created. * @return a valid java package name * @see {@link NameMangler#qualifiedPackageName(String)} */ public static String createJavaPackagePath(final String nsURI) { return new NameMangler().qualifiedPackageName(nsURI.toLowerCase(Locale.ENGLISH)).toLowerCase(); } /** * Search for another file next to this URI which ends on the passed suffix. */ public static String getSiblingName(final String location, final String siblingSuffix) { // strip the last part if (location.lastIndexOf(GenConstants.DOT) != -1) { return location.substring(0, location.lastIndexOf(GenConstants.DOT)) + siblingSuffix; } return location + siblingSuffix; } /** * @param eClass * the eClass to check if it is the document root * @return true if the passed eClass is a DocumentRoot * @see ExtendedMetaData#getDocumentRoot(org.eclipse.emf.ecore.EPackage) * @see ExtendedMetaData#isDocumentRoot(EClass) */ public static boolean isDocumentRoot(final EClass eClass) { final boolean result = ExtendedMetaData.INSTANCE.isDocumentRoot(eClass); return result; } /** * Formats a name so that it can be used as an identifier (like an enum value name) in a java source. * * The following formatting is done: * <ul> * <li>spaces are replaced by _</li> * </ul> * * @param name * the name to format * @return the formatted name */ public static String formatIdentifier(final String name) { return name.replaceAll(" ", "_"); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Based on the literal a default value is returned. If the literal is null then a zero length string is returned. * * @param literal * the literal defining the default value to create * @return a valid (from a type perspective) java default value */ public static String getStaticDefaultValue(AnnotationManager annotationManager, EDataType eDataType, final String literal) { if (eDataType instanceof EEnum) { return getStaticDefaultValue(annotationManager, (EEnum) eDataType, literal); } if (isObjectTypeWithEnumBaseType(eDataType)) { final EEnum enumDataType = ModelUtils.getEnumBaseDataTypeIfObject(eDataType); return getStaticDefaultValue(annotationManager, enumDataType, literal); } // first check if there the type extends a base Ecore/XML type (is often // the case) final EDataType baseType = getEcoreXMLDataType(eDataType); if (baseType != null && !useFactoryFor(baseType)) { // get an object variant of the default value final Object value; if (literal == null) { value = baseType.getDefaultValue(); } else { try { value = EcoreUtil.createFromString(baseType, literal); } catch (final Exception e) { // illegal value just return anything return "Exception: " + e.getMessage() + //$NON-NLS-1$ " literal:" //$NON-NLS-1$ + literal; // cause a syntax error } } if (value == null) { return "null"; //$NON-NLS-1$ } // then translate this value to a string representation // if the instanceclass is there, use that as it may be a primitive // type // (the class of the value is always the object type as it is an // object if (baseType.getInstanceClass() == null) { return Literals.toLiteral(value.getClass(), value); } return Literals.toLiteral(baseType.getInstanceClass(), value); } // always an object type at this point if (literal == null) { return GenConstants.NULL; } // not an ecore type or must use a factory, create the call to the // factory in that // case. There are different factories. The factory for the ecore/xml // types is the // ecore/xml factory, the factory for the other types is the // ModelFactory. // the current data type is an ecore type if (baseType == eDataType) { return createEcoreFactoryCall(baseType, literal); } // finally use the modelfactory createFromString return createModelFactoryCall(annotationManager, eDataType, literal); } private static String getStaticDefaultValue(AnnotationManager annotationManager, EEnum eNum, final String literal) { final EEnumLiteral enumLiteral; if (literal == null || literal.trim().length() == 0) { enumLiteral = null; } else { enumLiteral = eNum.getEEnumLiteralByLiteral(literal); } if (enumLiteral == null) { // never select the first one, always return null return GenConstants.NULL; } final EEnumModelGenAnnotation annotation = (EEnumModelGenAnnotation) annotationManager.getAnnotation(eNum, ModelcodegeneratorPackage.eINSTANCE.getEEnumModelGenAnnotation()); // NOTE: this assumes that in the template the names of the literals are upper-cased // this implements a strict dependency from the java code to the template, which // in general is undesirable but in this case unavoidable return annotation.getQualifiedClassName() + GenConstants.DOT + enumLiteral.getName().toUpperCase(); } /** * Creates a call to the {@link ModelFactory#createFromString(EDataType, String)} method which is placed inside of the * java model template. * * @param annotationManager * used to get the {@link EPackageModelGenAnnotation} * @param eDataType * the EDataType which defines the type * @param literalValue * the value which is passed to the createFromString method * @return the call to the generated ModelFactory createFromString method */ public static String createModelFactoryCall(AnnotationManager annotationManager, EDataType eDataType, final String literalValue) { final EPackageModelGenAnnotation annotation = getEPackageModelGenAnnotation(annotationManager, eDataType.getEPackage()); final String pkgClassName = annotation.getQualifiedClassName(); final StringBuilder result = new StringBuilder("(" //$NON-NLS-1$ + getInstanceClassName(eDataType) + ")"); //$NON-NLS-1$ result.append(pkgClassName + "." + GenConstants.MODELFACTORY_CONSTANT); //$NON-NLS-1$ result.append(".createFromString("); //$NON-NLS-1$ result.append(pkgClassName + ".INSTANCE.get" //$NON-NLS-1$ + ModelUtils.upCaseFirst(eDataType.getName()) + "EDataType()"); //$NON-NLS-1$ result.append(", "); //$NON-NLS-1$ // special case, if the instance is not a String then don't accept // empty string defaults, they are always null final String instanceClassName = getInstanceClassName(eDataType); if (!String.class.getName().equals(instanceClassName) && literalValue != null && literalValue.length() == 0) { result.append("null"); //$NON-NLS-1$ } else { result.append(Literals.toStringLiteral(literalValue)); } result.append(')'); return result.toString(); } private static EPackageModelGenAnnotation getEPackageModelGenAnnotation(AnnotationManager annotationManager, EPackage ePackage) { return (EPackageModelGenAnnotation) annotationManager.getAnnotation(ePackage, ModelcodegeneratorPackage.eINSTANCE.getEPackageModelGenAnnotation()); } /** * Creates a String which can be placed in the java source (through a template). The String represents a call to an * EFactory to create an instance of the default value passed in the literalValue. * * @param ecoreDataType * the ecore data type to create the factory call * @param literalValue * the literal value which is passed to the EFactory to create a type-safe insfance * @return a String which can be placed in the java source, initializing a member */ public static String createEcoreFactoryCall(final EDataType ecoreDataType, final String literalValue) { final StringBuilder result = new StringBuilder("(" //$NON-NLS-1$ + getInstanceClassName(ecoreDataType) + ")"); //$NON-NLS-1$ if (ecoreDataType.getEPackage() instanceof EcorePackage) { result.append(EcoreFactory.class.getName() + GenConstants.DOT_EINSTANCE); } else if (ecoreDataType.getEPackage() instanceof XMLTypePackage) { result.append(XMLTypeFactory.class.getName() + GenConstants.DOT_EINSTANCE); } else { result .append(ecoreDataType.getEPackage().getEFactoryInstance().getClass().getName() + GenConstants.DOT_EINSTANCE); } result.append(".createFromString("); //$NON-NLS-1$ if (ecoreDataType.getEPackage() instanceof EcorePackage) { result.append(EcorePackage.class.getName()); } else if (ecoreDataType.getEPackage() instanceof XMLTypePackage) { result.append(XMLTypePackage.class.getName()); } else { result.append(ecoreDataType.getEPackage().getClass().getName()); } result.append(GenConstants.DOT_EINSTANCE + ".get"); //$NON-NLS-1$ result.append(ModelUtils.upCaseFirst(ecoreDataType.getName())); result.append("(), "); //$NON-NLS-1$ final String instanceClassName = getInstanceClassName(ecoreDataType); if (!String.class.getName().equals(instanceClassName) && literalValue != null && literalValue.length() == 0) { result.append(GenConstants.NULL); } else { result.append(Literals.toStringLiteral(literalValue)); } result.append(')'); return result.toString(); } // /** // * Determines the instance class of the EDataType. Also considers super types of the passed // * EDataType. Note, null is returned when no class can be determined. This also happens in case // of // * a ClassNotFoundException. // * // * @param eDataType // * the EDataType to get the instanceClass for // * @return the Class reflecting the java type of the EDataType // * @see GenUtils#getInstanceClassName(EDataType) // */ // public static Class<?> getInstanceClass(EDataType eDataType) { // if (eDataType.getInstanceClass() != null) { // return eDataType.getInstanceClass(); // } // final ExtendedMetaData extendedMetaData = ExtendedMetaData.INSTANCE; // for (EDataType localDataType = eDataType; localDataType != null; localDataType = // extendedMetaData // .getBaseType(localDataType)) { // try { // if (localDataType == XMLTypePackage.eINSTANCE.getDate() // || localDataType == XMLTypePackage.eINSTANCE.getDateTime()) { // return Date.class; // } // final Class<?> instanceClass = localDataType.getInstanceClass(); // if (instanceClass != null) { // return instanceClass; // } // } catch (final Exception e) { // // can happen in case of class not found // // do nothing and continue with the next one // } // } // return null; // } /** * Guarantees that the returned class name is always an object and never a primitive type. Imports the class name, so * that it appears in the import list in the top of the java source. * * @param eDataType * the EDataType to compute the object class name for * @param instanceClassName * class name of the java type of the EDataType. If the class name contains a dot (.) then it is returned, * otherwise the java Object type is determined. * @return for a primitive type will return the Object type, for other classes calls {@link #getImportedClassName()} . * @see #getImportedClassName() */ public static String getObjectClassName(EDataType eDataType, String instanceClassName) { try { // if there is a dot then is an object anyway if (instanceClassName != null && instanceClassName.indexOf(GenConstants.DOT) != -1) { return instanceClassName; } // okay a primitive one, get the object variant return GenUtils.getPrimitiveObjectType(eDataType); } catch (final Throwable t) { // TODO: ignore to be robust, it will show up in the generated file t.printStackTrace(System.err); return GenConstants.EMPTY; } } /** * @return the instanceclassname of this EDataType. The method walks over the EDataType extension structure using * {@link ExtendedMetaData#INSTANCE #getBaseType(EDataType)} to use the instanceClass of a super simple type. * @see GenUtils#getInstanceClass(EDataType) */ public static String getInstanceClassName(EDataType eDataType) { if (isDateOrDateTime(eDataType)) { return Date.class.getName(); } Check.isFalse(isObjectTypeWithEnumBaseType(eDataType), "EDataType with base type EEnum should be handled differently, " + eDataType); //$NON-NLS-1$ if (eDataType.getInstanceClassName() != null) { return removeDollar(eDataType.getInstanceClassName()); } final ExtendedMetaData extendedMetaData = ExtendedMetaData.INSTANCE; for (EDataType localDataType = eDataType; localDataType != null; localDataType = extendedMetaData .getBaseType(localDataType)) { if (isDateOrDateTime(localDataType)) { return Date.class.getName(); } if (localDataType.getInstanceClassName() != null) { return removeDollar(localDataType.getInstanceClassName()); } } return removeDollar(eDataType.getInstanceClassName()); } /** * When in a xsd the enum element is nillable then EMF will create an extra data type called Object which has the enum * EDataType as the base. In this case always the enum instance needs to be returned * * @param eDataType * @return true if the eDataType has a base Enum type, false otherwise */ public static boolean isObjectTypeWithEnumBaseType(EDataType eDataType) { return null != ModelUtils.getEnumBaseDataTypeIfObject(eDataType); } /** * Determines if the passed EDataType is a Date or DateTime by checking: * <ul> * <li>if it is equal to the Date/DateTime EDataType of the XMLTypePackage</li> * <li>if the instance class is a Date or a XMLGregorianCalendar</li> * </ul> * * @param eDataType * @return */ public static boolean isDateOrDateTime(EDataType eDataType) { if (eDataType == XMLTypePackage.eINSTANCE.getDate() || eDataType == XMLTypePackage.eINSTANCE.getDateTime()) { return true; } else if (eDataType.getInstanceClass() != null && XMLGregorianCalendar.class.isAssignableFrom(eDataType.getInstanceClass())) { return true; } else if (XMLGregorianCalendar.class.getName().equals(eDataType.getInstanceClassName())) { return true; } else if (eDataType.getInstanceClass() != null && Date.class.isAssignableFrom(eDataType.getInstanceClass())) { return true; } return false; } /** * First follows base types in extended metadata, returning the first data type from Ecore or XMLTypes encountered. In * none, looks for a serializable Ecore data type that represents the Java type. This Ecore type matching is * unfortunately not so great, but required for backwards compatibility. */ public static EDataType getEcoreXMLDataType(EDataType eDataType) { // incomplete model not caught by model validation if (eDataType == null) { return null; } final ExtendedMetaData extendedMetaData = ExtendedMetaData.INSTANCE; for (EDataType ecoreDataType = eDataType; ecoreDataType != null; ecoreDataType = extendedMetaData .getBaseType(ecoreDataType)) { final String namespace = extendedMetaData.getNamespace(ecoreDataType); if (EcorePackage.eNS_URI.equals(namespace) || XMLTypePackage.eNS_URI.equals(namespace)) { return ecoreDataType; } } final String instanceClassName = eDataType.getInstanceClassName(); for (final EClassifier eClassifier : EcorePackage.eINSTANCE.getEClassifiers()) { if (eClassifier instanceof EDataType && eClassifier.getInstanceClassName().equals(instanceClassName)) { final EDataType ecoreDataType = (EDataType) eClassifier; if (ecoreDataType.isSerializable()) { return ecoreDataType; } } } return null; } /** * Determines if an EDataType value should be created through an EFactory or not. * * Note code is copied from EMF's {@link GenDataTypeImpl}, copyright to the authors of that class. * * @param ecoreDataType * the data type for which it is determined if values should be created through a factory. * @return true, use factory ( {@link EFactory#createFromString(EDataType, String)}), false otherwise */ public static boolean useFactoryFor(final EDataType ecoreDataType) { final String nsURI = ecoreDataType.getEPackage().getNsURI(); if (XMLTypePackage.eNS_URI.equals(nsURI)) { // Some XML types declare nebulous Object mappings. // They actually map to internal types that shouldn't be generated // into code. // final String name = ecoreDataType.getName(); return "Date".equals(name) //$NON-NLS-1$ || "DateTime".equals(name) //$NON-NLS-1$ || "Duration".equals(name) //$NON-NLS-1$ || "GDay".equals(name) //$NON-NLS-1$ || "GMonth".equals(name) //$NON-NLS-1$ || "GMonthDay".equals(name) //$NON-NLS-1$ || "GYear".equals(name) //$NON-NLS-1$ || "GYearMonth".equals(name) //$NON-NLS-1$ || "NOTATION".equals(name) //$NON-NLS-1$ || "QName".equals(name) //$NON-NLS-1$ || "Time".equals(name) //$NON-NLS-1$ || "ENTITIES".equals(name) //$NON-NLS-1$ || "ENTITIESBASE".equals(name) //$NON-NLS-1$ || "IDREFS".equals(name) //$NON-NLS-1$ || "IDREFSBase".equals(name) //$NON-NLS-1$ || "NMTOKENS".equals(name) //$NON-NLS-1$ || "NMTOKENSBase".equals(name); //$NON-NLS-1$ } else if (EcorePackage.eNS_URI.equals(nsURI)) { // EDate is far too often overridden to provide a different mapping, // and therefore the default is somewhat // obscure. // So, it's best to delegate to the factory. // if ("EDate".equals(ecoreDataType.getName())) { //$NON-NLS-1$ return true; } else if ("EJavaObject".equals(ecoreDataType.getName())) { //$NON-NLS-1$ final ExtendedMetaData extendedMetaData = ExtendedMetaData.INSTANCE; for (EDataType base = ecoreDataType; base != null; base = extendedMetaData.getBaseType(base)) { if (!extendedMetaData.getMemberTypes(base).isEmpty()) { return true; } } } return false; } return true; } /** * Returns the <code>Class</code> object associated with the class or interface with the given name, as from a * {@link java.lang.Class#forName(String)} call; however, if this classifier belongs to a package, that package's * class loader is used. Since the package may be model-specific code in another plug-in, its class loader may be able * to see classes that Ecore's can't. * * Note: copied from EMF's EClassifierImpl and adapted for use here * * NOTE, BEWARE: returns null when the name can not be resolved to a Class. */ public static Class<?> getClassForName(EDataType eDataType, String name) { if (!name.contains(GenConstants.DOT)) { return getPrimitiveClass(name); } if (eDataType instanceof EEnum) { return null; } try { final EPackage p = eDataType.getEPackage(); return p != null ? Class.forName(name, true, p.getClass().getClassLoader()) : Class.forName(name); } catch (ClassNotFoundException e) { // IGNORING on purpose return null; } } private static Class<?> getPrimitiveClass(String className) { if (className.equals(boolean.class.getName())) { return boolean.class; } else if (className.equals(byte.class.getName())) { return byte.class; } else if (className.equals(char.class.getName())) { return char.class; } else if (className.equals(double.class.getName())) { return double.class; } else if (className.equals(float.class.getName())) { return float.class; } else if (className.equals(int.class.getName())) { return int.class; } else if (className.equals(long.class.getName())) { return long.class; } else if (className.equals(short.class.getName())) { return short.class; } return null; } /** * Removes the dollar sign from a class name. The dollar sign appears sometimes with class names of inner classes. * * @param className * the class name to check/repair * @return a class name with dollar character replaced with a dot */ public static String removeDollar(String className) { if (!className.contains(GenConstants.DOLLAR)) { return className; } return className.replaceAll("\\" + GenConstants.DOLLAR, GenConstants.DOT); //$NON-NLS-1$ } }